package org.dfl.plugin.views.actions;

import java.util.HashSet;
import java.util.Set;

import org.dfl.core.data.types.CollectionType;
import org.dfl.core.data.types.Type;
import org.dfl.core.data.types.TypeManager;
import org.dfl.messages.Messages;
import org.dfl.plugin.DflPlugin;
import org.dfl.plugin.dialogs.DialogsManager;
import org.dfl.plugin.views.ViewsManager;
import org.dfl.plugin.views.debug.TreeElemPreview;
import org.dfl.plugin.views.debug.model.CollectionTreeElem;
import org.dfl.plugin.views.debug.model.DataTreeElem;
import org.dfl.plugin.views.debug.model.MapKeyTreeElem;
import org.dfl.plugin.views.debug.model.MapTreeElem;
import org.dfl.plugin.views.debug.model.TreeElem;
import org.dfl.plugin.views.debug.model.TreeElemFactory;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.actions.ActionDelegate;

/**
 * action that provide adding a content to data or token objects. 
 * It's used in a HistoriesTreeView and TokensTreeView (see mapping in plugin.xml file)
 * @author Piotr Wlodarczyk
 *
 */
public class AddContentAction extends ActionDelegate {
	
	private IStructuredSelection selection = StructuredSelection.EMPTY;

	/* (non-Javadoc)
	 * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
	 */
	public void selectionChanged(IAction action, ISelection sel) {
		if(sel instanceof IStructuredSelection)
			selection = (IStructuredSelection) sel;
		else 
			selection = StructuredSelection.EMPTY;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)
	 */
	public void run(IAction action) {
		if(selection.isEmpty()) return;
		Object parent = selection.getFirstElement();
		Object toRefresh = parent;
		
		if(parent instanceof MapKeyTreeElem && ((MapKeyTreeElem) parent).getChild()!=null){
			parent = ((MapKeyTreeElem) parent).getChild();
		}
		
		if(parent instanceof CollectionTreeElem){
			CollectionTreeElem parentElem = (CollectionTreeElem) parent;
			Type t = ((CollectionType)parentElem.getType()).getSubtypeContainer().getType();
			if(TypeManager.isAnyType(t)){
				Object[] children = parentElem.getChildren();
				if(children!=null && children.length>0){
					t=((DataTreeElem)children[0]).getType();
				}
			}
			 
			TreeElem child = TreeElemFactory.getEmptyInstance(parentElem,t,false);
			if(child!=null){
				synchronized (DflPlugin.class) {
					parentElem.addChild(child);
					parentElem.update();
				}
				ViewsManager.refreshViews(toRefresh);
			}
		}else if(parent instanceof MapTreeElem){
			MapTreeElem parentElem = (MapTreeElem) parent;
			Set<String> keys = new HashSet<String>(parentElem.getType().getSubkeysNames());
			Object[] children = parentElem.getChildren();
			if(children!=null && children.length>0){
				for(Object child : children){
					keys.remove(((MapKeyTreeElem)child).getKey());
				}
			}
			
			String key = (String) DialogsManager.openSelectDialog(Messages.AddContentAction_0,Messages.AddContentAction_0,keys,false);
			if(key!=null){
				if(!keys.contains(key) && parentElem.getType().getSubkeysNames().contains(key)){
					DialogsManager.openErrorDialog(Messages.AddContentAction_1);
					return;
				}
				Type t = parentElem.getType().getSubkeysNames().contains(key)?parentElem.getType().getSubtype(key).getType():TypeManager.getAnyType();
				synchronized (DflPlugin.class) {
					parentElem.addChild(new MapKeyTreeElem(parentElem,t,key));
					parentElem.update();
				}
				ViewsManager.refreshViews(toRefresh);
			}
		}else if(parent instanceof MapKeyTreeElem){
			MapKeyTreeElem parentElem = (MapKeyTreeElem) parent;
			Type t = parentElem.getType();
			if(TypeManager.isAnyType(t) || TypeManager.isSimpleAnyType(t)){
				// dla typu prostego wyciagnij typ danych 
				Object[] children = parentElem.getChildren();
				if(children!=null && children.length>0){
					t=((DataTreeElem)children[0]).getType();
				}
			}
			TreeElem child = TreeElemFactory.getEmptyInstance(parentElem,t,true);
			if(child!=null){
				synchronized (DflPlugin.class) {
					parentElem.addChild(child);
					parentElem.update();
				}
				ViewsManager.refreshViews(toRefresh);
				TreeElemPreview view = TreeElemPreview.getView();
				if(view!=null){
					view.selectionChanged(new DflSelectionChangedEvent(child));
				}
			}
		}
	}
}
